﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Bankeren.Engine.Cards
{
    /// <summary>
    /// This class represents a playingcard with suit and rank.
    /// </summary>
    [DataContract]
    public class Card : IEquatable<Card>
    {
        public static readonly Card Back = new Card(Suit.None, Rank.Back);

        #region Fields

        private Suit suit;
        private Rank rank;

        #endregion

        #region Properties

        /// <summary>
        /// The suit of the card.
        /// </summary>
        [DataMember]
        public Suit Suit
        {
            get
            {
                return this.suit;
            }
            private set
            {
                this.suit = value;
            }
        }

        /// <summary>
        /// The rank of the card.
        /// </summary>
        [DataMember]
        public Rank Rank
        {
            get
            {
                return this.rank;
            }
            private set
            {
                this.rank = value;
            }
        }

        /// <summary>
        /// Short name of the card. For use with image files.
        /// </summary>
        public string ShortName
        {
            get
            {
                return string.Concat(this.rank.Symbol, this.suit.Symbol);
            }
        }

        #endregion

        #region Ctor

        /// <summary>
        /// Public constructor for card.
        /// </summary>
        /// <param name="suit">This cards suit.</param>
        /// <param name="rank">This cards rank.</param>
        public Card(Suit suit, Rank rank)
        {
            this.Suit = suit;
            this.Rank = rank;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Override of the default ToString().
        /// </summary>
        /// <returns>The cards rank and suit.</returns>
        public override string ToString()
        {
            return string.Format("{0} of {1}", this.Rank, this.Suit);
        }

        /// <summary>
        /// For checking equality.
        /// </summary>
        /// <param name="other">The card to check for equality.</param>
        /// <returns>True if the cards are the same, false otherwise.</returns>
        public bool Equals(Card other)
        {
            return this.Rank.Equals(other.Rank) && this.Suit.Equals(other.Suit) ? true : false;
        }

        /// <summary>
        /// For checking equality.
        /// </summary>
        /// <param name="other">The object to check for equality.</param>
        /// <returns>True if the objects are the same, false otherwise.</returns>
        public override bool Equals(object obj)
        {
            Card card = obj as Card;
            if (card == null)
                return false;
            if (this.rank.Equals(card.Rank) && this.suit.Equals(card.Suit))
                return true;
            return false;
        }

        #endregion

        #region Comparing

        /// <summary>
        /// Class for grouping IComparers. For use with sorting.
        /// </summary>
        public static class Comparing
        {
            #region Properties

            /// <summary>
            /// IComparer for sorting by suit first, then rank.
            /// </summary>
            public static IComparer<Card> SuitFirst
            {
                get
                {
                    return new SuitComparer();
                }
            }

            /// <summary>
            /// IComparer for sorting by rank first, then suit.
            /// </summary>
            public static IComparer<Card> RankFirst
            {
                get
                {
                    return new RankComparer();
                }
            }

            #endregion

            #region Comparers

            /// <summary>
            /// This is the comparer class for comparing suit before rank.
            /// </summary>
            private class SuitComparer : IComparer<Card>
            {
                public int Compare(Card x, Card y)
                {
                    return x.Suit.CompareTo(y.Suit) == 0 ? x.Rank.CompareTo(y.Rank) : x.Suit.CompareTo(y.Suit);
                }
            }

            /// <summary>
            /// This is the comparer class for comparing rank before suit.
            /// </summary>
            private class RankComparer : IComparer<Card>
            {
                public int Compare(Card x, Card y)
                {
                    return x.Rank.CompareTo(y.Rank) == 0 ? x.Suit.CompareTo(y.Suit) : x.Rank.CompareTo(y.Rank);
                }
            }

            #endregion
        }

        #endregion
    }
}
